﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Graphics;

namespace KduneeShaders
{
    /// <summary>
    /// Ogólna klasa shaderów
    /// </summary>
    public class GeneralShader : Effect
    {
        /// <summary>
        /// Konstruktor shadera
        /// </summary>
        /// <param name="prototype">Shader, który zostanie użyty</param>
        public GeneralShader(Effect prototype)
            : base(prototype)
        {
        }

        private bool transparency = false;
        /// <summary>
        /// Czy uwzględniony będzie kanał alpha z tekstury
        /// </summary>
        public bool Transparency
        {
            get { return transparency; }
            set
            {
                transparency = value;
                this.Parameters["considerAlpha"].SetValue((value == true) ? 1 : 0);
            }
        }

        /// <summary>
        /// Tekstura diffuse
        /// </summary>
        public Texture2D Diffuse
        {
            get { return this.Parameters["diffuseTexture"].GetValueTexture2D(); }
            set { this.Parameters["diffuseTexture"].SetValue(value); }
        }

        /// <summary>
        /// Współczynnik ambient materiału
        /// </summary>
        public Vector4 MaterialAmbient
        {
            get { return this.Parameters["materialAmbient"].GetValueVector4(); }
            set { this.Parameters["materialAmbient"].SetValue(value); }
        }

        /// <summary>
        /// Współczynnik diffuse materiału
        /// </summary>
        public Vector4 MaterialDiffuse
        {
            get { return this.Parameters["materialDiffuse"].GetValueVector4(); }
            set { this.Parameters["materialDiffuse"].SetValue(value); }
        }

        /// <summary>
        /// Współczynnik specular materiału
        /// </summary>
        public Vector4 MaterialSpecular
        {
            get { return this.Parameters["materialSpecular"].GetValueVector4(); }
            set { this.Parameters["materialSpecular"].SetValue(value); }
        }

        /// <summary>
        /// Współczynnik ambient światła
        /// </summary>
        public Vector4 LightAmbient
        {
            get { return this.Parameters["lightAmbient"].GetValueVector4(); }
            set { this.Parameters["lightAmbient"].SetValue(value); }
        }

        /// <summary>
        /// Współczynnik diffuse światła
        /// </summary>
        public Vector4 LightDiffuse
        {
            get { return this.Parameters["lightDiffuse"].GetValueVector4(); }
            set { this.Parameters["lightDiffuse"].SetValue(value); }
        }

        /// <summary>
        /// Współczynnik specular światła
        /// </summary>
        public Vector4 LightSpecular
        {
            get { return this.Parameters["lightSpecular"].GetValueVector4(); }
            set { this.Parameters["lightSpecular"].SetValue(value); }
        }

        /// <summary>
        /// Aktualizacja shadera
        /// </summary>
        /// <param name="delta">Ilość czasu, jaki upłynął</param>
        /// <param name="eye">Pozycja obserwatora</param>
        /// <param name="light">Pozycja światła</param>
        public virtual void Update(float delta, Vector3 eye, Vector3 light)
        {
            Parameters["eyePosition"].SetValue(eye);
            Parameters["lightPosition"].SetValue(light);
        }

        /// <summary>
        /// Ustaw macierze, niezbędne do określenia przekształcenia obiektu
        /// </summary>
        /// <param name="obj2world">Macierz transformacji obiektu do świata</param>
        /// <param name="world2projection">Macierz transformacji świata do powierzchni rzutowania</param>
        public void SetMatrices(Matrix obj2world, Matrix world2projection)
        {
            Parameters["obj2projection"].SetValue(obj2world * world2projection);
            Parameters["obj2world"].SetValue(obj2world);
            Parameters["world2obj"].SetValue(Matrix.Invert(obj2world));
        }
    }
}
